package com.settlement.system.service.impl;

import com.settlement.system.common.exception.ServiceException;
import com.settlement.system.common.util.common.JsonUtil;
import com.settlement.system.mapper.BaseMapper;
import com.settlement.system.model.entity.common.SinglePage;
import com.fasterxml.jackson.core.io.JsonEOFException;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Ximi
 * Date 2018-11-28
 */
@Slf4j
public abstract class BaseServiceImpl{

    private BaseMapper baseMapper;

    /**
     * init
     * @return
     */
    public abstract BaseMapper init();

    @PostConstruct
    private void initConfig(){
        baseMapper = init();
    }

    /**
     * 插入一条数据
     * @param modelType
     * @return Integer
     */
    public <ModelType> Integer insert(ModelType modelType) throws ServiceException {
        try {
            return baseMapper.insert(modelType);
        } catch (Exception ex){
            log.error("保存数据异常",ex);
            throw new ServiceException("保存数据异常",ex);
        }
    }

    /**
     * 更新数据
     * @param modelType
     * @return Integer
     */
    public  <ModelType> Integer update(ModelType modelType) throws ServiceException{
        try {
            return baseMapper.update(modelType);
        } catch (Exception ex){
            log.error("更新数据异常",ex);
            throw new ServiceException("更新数据异常",ex);
        }
    }

    /**
     * 删除数据
     * @param modelType
     * @return Integer
     */
    public <ModelType> Integer deleteById(ModelType modelType) throws ServiceException{
        try {
            return baseMapper.deleteById(modelType);
        } catch (Exception ex){
            log.error("删除数据异常",ex);
            throw new ServiceException("删除数据异常",ex);
        }
    }

    public Integer deleteByParams(Map<String,Object> params) throws ServiceException{
        try {
            return baseMapper.deleteByParams(params);
        } catch (Exception ex){
            log.error("删除数据异常",ex);
            throw new ServiceException("删除数据异常",ex);
        }
    }

    /**
     * 获取数量
     * @param params
     * @return
     */
    public Integer selectCount(Map<String,Object> params) throws ServiceException{
        try {
            return baseMapper.selectCount(params);
        } catch (Exception ex){
            log.error("获取数据数量异常",ex);
            throw new ServiceException("获取数据数量异常",ex);
        }
    }

    /**
     * 获取分页列表
     * @param page
     * @param params
     * @return
     */
    public <ModelType> List<ModelType> selectByPage(SinglePage page, Map<String,Object> params,String orderByField,String orderBy) throws ServiceException{
        try {
            return baseMapper.selectByPage(page,params,orderByField,orderBy);
        } catch (Exception ex){
            log.error("获取分页数据异常",ex);
            throw new ServiceException("获取分页数据异常",ex);
        }
    }

    /**
     * 根据参数获取列表
     * @param params
     * @return
     */
    public <ModelType> List<ModelType> selectByParam(Map<String,Object> params) throws ServiceException{
        try {
            return baseMapper.selectByParam(params);
        } catch (Exception ex){
            log.error("获取数据列表异常",ex);
            throw new ServiceException("获取数据列表异常",ex);
        }
    }

    /**
     * 批量保持
     * @param list
     * @param <ModelType>
     * @throws ServiceException
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public <ModelType> void save(List<ModelType> list) throws ServiceException{
        try {
            for(ModelType info:list){
                baseMapper.insert(info);
            }
        } catch (Exception ex){
            log.error("批量保持异常",ex);
            throw new ServiceException("批量保持异常",ex);
        }
    }

    /**
     * 通过handler获取数据
     * @param params
     * @param handler
     * @param <ModelType>
     */
    public <ModelType> void getDataByHandler(Map<String,Object> params, ResultHandler<ModelType> handler) throws ServiceException{
        try {
            baseMapper.getDataByHandler(params,handler);
        } catch (Exception ex){
            log.error("流式导出异常",ex);
            throw new ServiceException(ex);
        }
    }

    public void getMapDataByHandler(Map<String,Object> params, ResultHandler<Map<String,Object>> handler) throws ServiceException{
        try {
            baseMapper.getMapDataByHandler(params,handler);
        } catch (Exception ex){
            log.error("流式导出异常",ex);
            throw new ServiceException(ex);
        }
    }



    /**
     * 通过handler获取数据
     * @param params
     * @param handler
     * @param <ModelType>
     */
    public <ModelType> void getPageDataByHandler(Map<String,Object> params, ResultHandler<ModelType> handler) throws ServiceException{
        try {
            baseMapper.getPageDataByHandler(params,handler);
        } catch (Exception ex){
            log.error("流式导出异常",ex);
            throw new ServiceException(ex);
        }
    }

    /**
     * 通过id,批量删除明细
     *
     * @param list 数据列表
     * @return 删除的数量
     * @throws ServiceException
     */
    @Transactional(rollbackFor = ServiceException.class)
    public <ModelType> Integer batchDelete(List<ModelType> list) throws ServiceException{
        try {
            Integer deleteNumber = 0;
            for(ModelType info:list){
                deleteNumber += baseMapper.deleteById(info);
            }

            return deleteNumber;
        } catch (Exception ex){
            throw new ServiceException("批量删除异常",ex);
        }
    }

    /**
     * 保持一个不重复的数据列表,当重复的时候,抛出DuplicateKeyException异常,
     * 可以通过DuplicateKeyException.getMessage 获取重复的数据
     * <p>
     * DuplicateKeyException.getMessage 里面包含所有的重复的数据
     *
     * @param list
     * @param <ModelType>
     * @return number of save data
     * @throws ServiceException
     * @throws DuplicateKeyException
     */
    @Transactional(rollbackFor = {ServiceException.class},noRollbackFor = {DuplicateKeyException.class})
    public <ModelType> Integer saveNoDuplicateList(List<ModelType> list) throws ServiceException,DuplicateKeyException{
        List<ModelType> duplicateList = new ArrayList<>();
        for(ModelType info:list) {
            try {
                baseMapper.insert(info);
            } catch (Exception ex){
                if(ex.getCause() != null && ex.getCause() instanceof SQLIntegrityConstraintViolationException){
                    duplicateList.add(info);
                }else {
                    log.error("保存异常",ex);
                    throw new ServiceException("保存异常",ex);
                }
            }
        }
        if(!CollectionUtils.isEmpty(duplicateList)){
            throw new DuplicateKeyException(JsonUtil.getJsonOrToString(duplicateList));
        }
        return list.size();
    }

    /**
     * 根据model获取单条
     * @param modelType
     * @return
     */
    public <ModelType> ModelType selectSingleByModel(ModelType modelType) throws ServiceException {
        try {
            return baseMapper.selectSingleByModel(modelType);
        } catch (Exception ex){
            log.error("通过model获取单条数据异常",ex);
            throw new ServiceException("通过model获取单条数据异常",ex);
        }
    }
}
